
package cn.live.kyle.questionnaire.question;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.content.Context;
import android.view.ViewGroup;

public class QuestionDomParser {
    public static final String TAG_TITLE = "title";
    public static final String TAG_PAGE = "page";
    public static final String TAG_QUESTION = "question";
    public static final String TAG_OPTION = "option";
    public static final String TAG_ID_QUESTION = "idQuestion";

    public static final String ATTR_TYPE = "type";
    public static final String ATTR_TYPE_TEXT = "text";
    public static final String ATTR_TYPE_RADIO = "radio";
    public static final String ATTR_TYPE_MULTISELECT = "muliselect";
    public static final String ATTR_TYPE_DATE = "date";

    public static final String ATTR_TITLE = "title";

    public static final String ATTR_ANSWER = "answer";

    public static final String ATTR_INPUT_TYPE = "inputType";
    public static final String ATTR_INPUT_TYPE_PHONE = "phone";
    public static final String ATTR_INPUT_TYPE_DECIMAL = "decimal";

    public static final String ATTR_EMPTY = "empty";
    public static final String ATTR_EMPTY_ENABLE = "enabled";

    public static final String ATTR_INDEX = "index";

    private Document mDocument;

    private String mQuestionTitle;
    private NodeList mPageList;

    public QuestionPage createQuestionPage(int index, ViewGroup container) {
        Element page = (Element) mPageList.item(index);
        return new QuestionPage(page, container);
    }

    public QuestionCheckPage createQuestionCheckPage(int start, int count, ViewGroup container) {
        return new QuestionCheckPage(mPageList, start, count, container);
    }

    public QuestionCheckPage createQuestionCheckPage(ViewGroup container) {
        return new QuestionCheckPage(mPageList, container);
    }

    public String getQuestionTitle() {
        return mQuestionTitle;
    }

    public int getQuestionPageCount() {
        return mPageList.getLength();
    }

    public void parse(InputStream is) {
        try {
            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                    .newDocumentBuilder();
            mDocument = builder.parse(is);
            Element root = mDocument.getDocumentElement();

            NodeList titleList = root.getElementsByTagName(TAG_TITLE);
            if (titleList != null && titleList.getLength() >= 1) {
                Element titleElement = (Element) titleList.item(0);
                mQuestionTitle = titleElement.getAttribute(ATTR_TITLE);
            }

            mPageList = root.getElementsByTagName(TAG_PAGE);
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void generate(Context context) {
        try {
            Transformer transformer = TransformerFactory.newInstance()
                    .newTransformer();
            Source xmlSource = new DOMSource(mDocument);
            String fileName = generateFileName();
            Result outputTarget = new StreamResult(new File(
                    context.getFilesDir(), fileName));
            transformer.transform(xmlSource, outputTarget);
        } catch (TransformerConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerFactoryConfigurationError e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (TransformerException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public NodeList getQuestionList() {
        Element root = mDocument.getDocumentElement();
        return root.getElementsByTagName(TAG_QUESTION);
    }

    private String generateFileName() {
        int[] idQuestionIndexArray = getIdQuestionIndexArray();
        if (idQuestionIndexArray != null) {
            String idString = getIdStringAnswer(idQuestionIndexArray);
            int hash = getSDBMHash(idString);
            return Integer.toHexString(hash) + ".xml";
        }

        return "persons.xml";
    }

    private int[] getIdQuestionIndexArray() {
        Element root = mDocument.getDocumentElement();
        NodeList idList = root.getElementsByTagName(TAG_ID_QUESTION);
        int count = idList.getLength();
        if (idList != null && count >= 1) {
            int[] indexArray = new int[count];
            for (int i = 0; i < count; i++) {
                Element idElement = (Element) idList.item(i);
                String indexString = idElement.getAttribute(ATTR_INDEX);
                indexArray[i] = Integer.valueOf(indexString);
            }

            return indexArray;
        }

        return null;
    }

    private String getIdStringAnswer(int[] indexArray) {
        String idString = "";
        Element root = mDocument.getDocumentElement();
        NodeList questionList = root.getElementsByTagName(TAG_QUESTION);
        for (int index : indexArray) {
            Element questionElement = (Element) questionList.item(index);
            idString += questionElement.getAttribute(ATTR_ANSWER);
        }
        return idString;
    }

    private int getSDBMHash(String s) {
        int hash = 0;
        int l = s.length();
        for (int i = 0; i < l; i++) {
            hash = s.charAt(i) + (hash << 6) + (hash << 16) - hash;
        }
        return (hash & 0x7fffffff);
    }
}
